﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TfsSpam.Differ
{
    /// <summary>
    /// The LineSource enumeration defines the source of a <see cref="DifferenceLine"/>,
    /// whether it came from the old file or the new file.
    /// </summary>
    public enum LineSource
    {
        /// <summary>
        /// The line originates from the old file.
        /// </summary>
        Old,

        /// <summary>
        /// The line originates from the new file.
        /// </summary>
        New
    }

    /// <summary>
    /// The LineType enumeration defines the type of a <see cref="DifferenceLine"/>:
    /// context, deleted, added or highlighted.
    /// </summary>
    public enum LineType
    {
        /// <summary>
        /// The line provides context.
        /// </summary>
        Context,

        /// <summary>
        /// The line was deleted.
        /// </summary>
        Deleted,

        /// <summary>
        /// The line was added.
        /// </summary>
        Added,
    }

    /// <summary>
    /// The DifferenceLine class represents a line of text included
    /// in a difference operation and provides information about the
    /// type of line, where it belongs and so on.
    /// </summary>
    public class DifferenceLine
    {
        #region -- Constructor
        /// <summary>
        /// Standard constructor for the class, sets the basic properties
        /// for a line that's included as part of a differencing operation.
        /// </summary>
        /// <param name="text">The text of the line.</param>
        /// <param name="lineNumber">The number of the line in the source file.</param>
        /// <param name="source">The source of the line.</param>
        /// <param name="type">The type of line.</param>
        public DifferenceLine( string text, long lineNumber, LineSource source, LineType type )
        {
            LineText = text;
            LineNumber = lineNumber;
            LineSource = source;
            LineType = type;
        }
        #endregion

        #region -- Public properties
        /// <summary>
        /// The text on the line.
        /// </summary>
        public string LineText { get; private set; }

        /// <summary>
        /// The number of the line in the file.
        /// </summary>
        public long LineNumber { get; private set; }

        /// <summary>
        /// The source of the line.
        /// </summary>
        public LineSource LineSource { get; private set; }

        /// <summary>
        /// The type of the line.
        /// </summary>
        public LineType LineType { get; private set; }

        /// <summary>
        /// The highlight text for this line (if any).
        /// </summary>
        public string HighlightText { get; private set; }

        /// <summary>
        /// Does this line have any highlight information?
        /// </summary>
        public bool HasHighlight
        {
            get { return !string.IsNullOrEmpty( HighlightText ); }
        }
        #endregion

        #region -- Code highlight processing
        /// <summary>
        /// Merges this line with <paramref name="lineToMerge"/>, updating
        /// the <see cref="LineType"/>, <see cref="HighlightPrefix"/> and
        /// <see cref="HighlightText"/> properties with the values from 
        /// <paramref name="lineToMerge"/>.
        /// </summary>
        /// <param name="lineToMerge">The line this line should be merged with.</param>
        internal void Merge( DifferenceLine lineToMerge )
        {
            LineType = lineToMerge.LineType;
            HighlightText = lineToMerge.HighlightText;
        }

        /// <summary>
        /// Processes the defined code highlight prefixes for this line,
        /// setting the <see cref="HighlightPrefix"/> and <see cref="HighlightText"/>
        /// properties if a match is found.
        /// </summary>
        /// <param name="highlightPrefixes">The list of prefixes recognized for code highlighting.</param>
        internal void ProcessHighlightPrefixes( List<string> highlightPrefixes )
        {
            // Process each defined highlight prefix (if any).
            foreach ( string prefix in highlightPrefixes )
            {
                int prefixIndex = LineText.IndexOf( prefix, StringComparison.OrdinalIgnoreCase );

                if ( prefixIndex != -1 )
                {
                    // We found a matching highlight prefix. Set the highlight
                    // information and return, ignoring any additional prefixes
                    // that may be present.
                    HighlightText = LineText.Substring( prefixIndex );
                    return;
                }
            }
        }
        #endregion
    }
}
